using System;
using System.Collections.Generic;
using System.Text;

namespace ProgrammingLanguageNr1
{
	public class GlobalScope : BaseScope
	{
		public GlobalScope ()
		{
			m_name = "global";
			initTypeSystem();
			initBuiltInFunctions();
		}
		
		protected void initTypeSystem() {
			define(new BuiltInTypeSymbol("float"));
			define(new BuiltInTypeSymbol("void"));
			define(new BuiltInTypeSymbol("string"));
		}
		
		protected void initBuiltInFunctions() {
			
			AST printFunctionParameterList = new AST(new Token(Token.TokenType.PARAMETER_LIST, "<PARAMETER_LIST>"));
			printFunctionParameterList.addChild(createParameterDefinition("string", "s"));
			AST printFunctionNode = createFunctionDefinitionNode("void", "print", printFunctionParameterList);
			define(new FunctionSymbol(null, "print", (SprakType)resolve("void"), printFunctionNode));
			
			AST sqrtFunctionParameterList = new AST(new Token(Token.TokenType.PARAMETER_LIST, "<PARAMETER_LIST>"));
			sqrtFunctionParameterList.addChild(createParameterDefinition("float", "n"));
			AST sqrtFunctionNode = createFunctionDefinitionNode("void", "sqrt", sqrtFunctionParameterList);
			define(new FunctionSymbol(null, "sqrt", (SprakType)resolve("float"), sqrtFunctionNode));
		}
		
		private AST_FunctionDefinitionNode createFunctionDefinitionNode(string returnTypeName, string functionName, AST parameterList) {
			AST_FunctionDefinitionNode functionNode = 
				new AST_FunctionDefinitionNode(	new Token(Token.TokenType.FUNC_DECLARATION, 
												"<INTERNAL_FUNC_DECLARATION>") );
			
			functionNode.addChild(new Token(Token.TokenType.NAME, returnTypeName));
			functionNode.addChild(new Token(Token.TokenType.NAME, functionName));
			functionNode.addChild(parameterList);
			functionNode.addChild(new Token(Token.TokenType.STATEMENT_LIST, "<EMPTY_STATEMENT_LIST>"));
			
			return functionNode;
		}
			
		private AST createParameterDefinition(string typeName, string variableName) {
			AST parameter = new AST(new Token(Token.TokenType.PARAMETER, "<PARAMETER>"));
			parameter.addChild(new AST(new Token(Token.TokenType.NAME, typeName)));
			parameter.addChild(new AST(new Token(Token.TokenType.NAME, variableName)));
			return parameter;
		}
	}
}

